#import "RNLayoutViewProtocol.h"
#import "RNLayoutHelper.h"

NSString * const RNHeightTypeKey = @"heightType";
NSString * const RNWidthTypeKey = @"widthType";
NSString * const RNHorizontalPositionTypeKey = @"horizontalLayoutType";
NSString * const RNVerticalPositionTypeKey = @"verticalLayoutType";
NSString * const RNTopPaddingKey = @"topPadding";
NSString * const RNBottomPaddingKey = @"bottomPadding";
NSString * const RNLeftPaddingKey = @"leftPadding";
NSString * const RNRightPaddingKey = @"rightPadding";
NSString * const RNViewKey = @"view";

@interface RNLayoutHelper (RNLayoutHelperPrivateMethods)
-(NSArray *)coderKeys_;
@end;


@implementation RNLayoutHelper

@synthesize view = view_;
@synthesize heightType = heightType_;
@synthesize widthType = widthType_;
@synthesize horizontalLayoutType = horizontalType_;
@synthesize verticalLayoutType = verticalType_;
@synthesize topPadding = topPadding_;
@synthesize bottomPadding = bottomPadding_;
@synthesize leftPadding = leftPadding_;
@synthesize rightPadding = rightPadding_;

-(id)init {
    return [self initWithView:nil];
}

- (id)initWithView:(NSView<RNLayoutView> *)theView {
	if(!(self = [super init]))
		return nil;
	
    [self setView:theView];

	return self;
}

- (void)encodeWithCoder:(NSCoder*)theCoder {	
    for (NSString *key in [self coderKeys_])
        [theCoder encodeObject:[self valueForKey:key] forKey:key];
    [theCoder encodeConditionalObject:[self view] forKey:RNViewKey];
}

- (id)initWithCoder:(NSCoder*)theCoder {		
    
    for (NSString *key in [self coderKeys_])
        [self setValue:[theCoder decodeObjectForKey:key] forKey:key];
    
    [self setView:[theCoder decodeObjectForKey:RNViewKey]];
	return self;
}

- (NSArray *)coderKeys_ {
    return [NSArray arrayWithObjects:RNHeightTypeKey, RNWidthTypeKey, RNHorizontalPositionTypeKey, RNVerticalPositionTypeKey, RNTopPaddingKey, RNBottomPaddingKey, RNLeftPaddingKey, RNRightPaddingKey, nil];
}

- (void)setPadding:(CGFloat)padding {
    [self setLeftPadding:padding];
    [self setRightPadding:padding];
    [self setTopPadding:padding];
    [self setBottomPadding:padding];
}

- (void)setHorizontalPadding:(CGFloat)padding {
    [self setLeftPadding:padding];
    [self setRightPadding:padding];
}

- (void)setVerticalPadding:(CGFloat)padding {
    [self setTopPadding:padding];
    [self setBottomPadding:padding];
}

-(void)setView:(NSView<RNLayoutView> *)containerView {
    view_ = containerView;
    viewRespondsToSubviewsNeedResizing_ = [containerView respondsToSelector:@selector(subviewsNeedResizing)];
}

-(void)tile {
    NSRect selfFrame = [[self view] frame];
    CGFloat widthAvailable = NSWidth(selfFrame);
    CGFloat heightAvailable = NSHeight(selfFrame);
    NSArray *originalSubviews = [[self view] subviews];
    NSMutableArray *subviews = [originalSubviews mutableCopy];
    for (NSView *view in originalSubviews) {
        if (![view conformsToProtocol:@protocol(RNLayoutView)])
            [subviews removeObject:view];
    }
    if ([subviews count] == 0)
        return;
    
    NSUInteger filledWidthCount = [subviews count];
    NSUInteger filledHeightCount = [subviews count];
    CGFloat centerWidthUsed = 0;
    CGFloat centerHeightUsed = 0;
    
    // First time through the subviews, adjust the available width and height so we know how to set the 'fill' views in the next loop
    for (NSView<RNLayoutView> *childView in subviews) {        
        if ([[childView layoutHelper] widthType] == RNSizeFixed) {
            filledWidthCount--;
            CGFloat childWidth = NSWidth([childView frame]) + [[childView layoutHelper] leftPadding] + [[childView layoutHelper] rightPadding];
            if ([[childView layoutHelper] horizontalLayoutType] != RNHorizontalCenter)
                widthAvailable -= childWidth;
            else if ((childWidth - centerWidthUsed) > 0) { 
                widthAvailable -= childWidth - centerWidthUsed;
                centerWidthUsed = childWidth;
            }
        }
        if ([[childView layoutHelper] heightType] == RNSizeFixed) {
            filledHeightCount--;
            CGFloat childHeight = NSHeight([childView frame]) + [[childView layoutHelper] topPadding] + [[childView layoutHelper] bottomPadding];
            if ([[childView layoutHelper] verticalLayoutType] != RNVerticalCenter)
                heightAvailable -= childHeight;
            else if ((childHeight - centerHeightUsed) > 0) {
                heightAvailable -= childHeight - centerHeightUsed;
                centerHeightUsed = childHeight;
            }
        }
    }
    CGFloat fillWidth = (filledWidthCount > 0) ? (widthAvailable / filledWidthCount) : 0.0f;
    CGFloat fillHeight = (filledHeightCount > 0) ? (heightAvailable / filledHeightCount) : 0.0f;
    CGFloat leftPlaceholder = 0.0f;
    CGFloat rightPlaceholder = NSWidth(selfFrame);
    CGFloat topPlaceholder = NSHeight(selfFrame);
    CGFloat bottomPlaceholder = 0.0f;
        
    // Second time through the subviews, set the frame for each
    for (NSView<RNLayoutView> *childView in subviews) {        
        NSRect childFrame = [childView frame];
        RNLayoutHelper *childHelper = [childView layoutHelper];
        CGFloat childLeftPadding = [childHelper leftPadding];
        CGFloat childRightPadding = [childHelper rightPadding];
        CGFloat childTopPadding = [childHelper topPadding];
        CGFloat childBottomPadding = [childHelper bottomPadding];
        
        // Size
        if ([childHelper widthType] == RNSizeFill) 
            childFrame.size.width = ([childHelper horizontalLayoutType] == RNHorizontalCenter) ? 
                                    (NSWidth(selfFrame) - childLeftPadding - childRightPadding) : 
                                    (fillWidth - childLeftPadding - childRightPadding);
        if ([childHelper heightType] == RNSizeFill)
            childFrame.size.height = ([childHelper verticalLayoutType] == RNVerticalCenter) ? 
                                     (NSHeight(selfFrame) - childTopPadding - childBottomPadding) : 
                                     (fillHeight - childTopPadding - childBottomPadding);
        
        // Horizontal Position
        switch ([childHelper horizontalLayoutType]) {
            case RNHorizontalLeft:
                childFrame.origin.x = leftPlaceholder + childLeftPadding;
                leftPlaceholder = NSMaxX(childFrame) + childRightPadding;
                break;
                
            case RNHorizontalRight:
                childFrame.origin.x = rightPlaceholder - childRightPadding - NSWidth(childFrame);
                rightPlaceholder = NSMinX(childFrame) - childLeftPadding;
                break;
                
            default: // RNHorizontalCenter
                childFrame.origin.x = floor(NSWidth(selfFrame)/2) - floor(NSWidth(childFrame)/2);
        }
        
        // Vertical Position
        switch ([childHelper verticalLayoutType]) {
            case RNVerticalBottom:
                childFrame.origin.y = bottomPlaceholder + childBottomPadding;
                bottomPlaceholder = NSMaxY(childFrame) + childTopPadding;
                break;

            case RNVerticalTop:
                childFrame.origin.y = topPlaceholder - childTopPadding - NSHeight(childFrame);
                topPlaceholder = NSMinY(childFrame) - childBottomPadding;
                break;
                
            default: // RNVerticalCenter
                childFrame.origin.y = floor(NSHeight(selfFrame)/2) - floor(NSHeight(childFrame)/2);
        }
        
        [childView setFrame:childFrame];
    }
    if (viewRespondsToSubviewsNeedResizing_ && (widthAvailable < 0 || heightAvailable < 0))
        [[self view] subviewsNeedResizing];
}

@end
